﻿using Bentley.DgnPlatformNET;
using Bentley.GeometryNET;
using CheccCoverplateCulvertAssemble.Conmmon;
using CheccCoverplateCulvertAssemble.Intefaces;
using Newtonsoft.Json.Linq;
using System.Data;
using System.IO;
using System.Security.Permissions;

namespace CheccCoverplateCulvertAssemble.Entity;

public abstract class RebarBase :  IElementECProperty, IStandardECProperty
{
    protected readonly ConstructingEntity _constructingEntity;
    public string RebarGroupNumber { get; set; }
    /// <summary>
    /// 钢筋直径
    /// </summary>
    public double Diameter { get; set; }
    /// <summary>
    /// 钢筋牌号
    /// </summary>
    public string Grades { get; set; }
    /// <summary>
    /// 钢筋类型
    /// </summary>
    public RebarType RebarType { get; }
    /// <summary>
    /// 钢筋基线
    /// </summary>
    public CurveVector BaseLine { get; set; }
    /// <summary>
    /// 起点旋转角度
    /// </summary>
    public double StartRotationAngle { get; set; }
    /// <summary>
    /// 终点旋转角度
    /// </summary>
    public double EndRotationAngle { get; set; }
    public double HookDiameter { get; set; }
    public string EntityEcPropertyInfoFile
    {
        get
        {
            string jsonString = File.ReadAllText(GeneralHelpers.LevelAndMatrialJsonFilePath);
            var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject>(jsonString);
            var culvertTypeInfo = this._constructingEntity.CulvertType == CulvertType.BoxCulvert ? "BoxCulvertFiles" : this._constructingEntity.CulvertType == CulvertType.CircularCulvert ? "CircularCulvertFiles" : "SlabCulvertFiles";
            var culvertFilePathArray = obj[culvertTypeInfo] as JArray;
            var ecFileName = this.GetEcFileName(this._constructingEntity.CulvertType, this.RebarType);
            return $@"{GeneralHelpers.WorkSpacePath}{culvertFilePathArray[0].ToString().Substring(1)}\{ecFileName}";
        }
    }
    protected string GetEcFileName(CulvertType culvertType, RebarType rebarType)
    {
        if (culvertType == CulvertType.SlabCulvert && rebarType == RebarType.Ribbed) return "盖板涵_带肋钢筋_构造体.csv";
        if (culvertType == CulvertType.SlabCulvert && rebarType == RebarType.NoRibbed) return "盖板涵_光圆钢筋_构造体.csv";
        return null;
    }
    protected RebarBase(ConstructingEntity constructingEntity, string rebarGroupNumber, double diameter, string grades, RebarType rebarType, CurveVector baseLine, double hookDiameter = 0.0, double startRotationAngle = 0.0, double endRotationAngle = 0.0)
    {
        this._constructingEntity = constructingEntity;
        this.RebarGroupNumber = rebarGroupNumber;
        this.Diameter = diameter;
        this.Grades = grades;
        this.RebarType = rebarType;
        this.BaseLine = baseLine;
        this.HookDiameter = hookDiameter;
        this.StartRotationAngle = startRotationAngle;
        this.EndRotationAngle = endRotationAngle;
    }
    public Element CreateEntityModel()
    {
        CurveVector guideLine = this.CreateGuideLineOfRebar();
        SolidKernelEntity rebarEntity = CulvertHelpers.CreateBodyFromSweep(guideLine, this.CreateRebarSection(), GeneralHelpers.ActiveDgnModel);
        if (rebarEntity != null)
        {
            Convert1.BodyToElement(out Element ehOut, rebarEntity, null, Session.Instance.GetActiveDgnModel());
            //if (ehOut.IsValid)
            //{
            //    var levelAndMaterialName = this.GetLevelAndMaterialFromJsonFile(GeneralHelpers.LevelAndMatrialJsonFilePath);
            //    GeneralHelpers.AssignLevelToElement(ehOut, levelAndMaterialName.levelName); //元素赋予图层
            //    StatusInt statusInt = ehOut.AddToModel();
            //    if (statusInt == StatusInt.Success)
            //    {
            //        var ecPropertyList = ItemTypeHelpers.GetECPropertyList(this.EntityEcPropertyInfoFile);
            //        this.CreateElementECProperty(ehOut, ecPropertyList);
            //    }
            //    GeneralHelpers.AssignMaterialToElement(ehOut, levelAndMaterialName.materialName); //元素赋予材质
            //}
            return ehOut;
        }
        return null;
    }

    public void AddElmentMaterial(Element element)
    {
        var levelAndMaterialName = this.GetLevelAndMaterialFromJsonFile(GeneralHelpers.LevelAndMatrialJsonFilePath);
        GeneralHelpers.AssignLevelToElement(element, levelAndMaterialName.levelName); //元素赋予图层
        //StatusInt statusInt = element.AddToModel();
        //if (statusInt == StatusInt.Success)
        //{
            var ecPropertyList = ItemTypeHelpers.GetECPropertyList(this.EntityEcPropertyInfoFile);
            this.CreateElementECProperty(element, ecPropertyList);
        //}
        GeneralHelpers.AssignMaterialToElement(element, levelAndMaterialName.materialName); //元素赋予材质
    }

    protected (string levelName, string materialName) GetLevelAndMaterialFromJsonFile(string levelAndMatrialJsonFilePath)
    {
        string jsonString = File.ReadAllText(@levelAndMatrialJsonFilePath);
        var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<JObject>(jsonString);
        var contructorOfRebar = this.GetConstuctorInfoOfRebar(this._constructingEntity.CulvertComponentType, this._constructingEntity.CulvertType);
        //var contructorOfRebar = "SlabCulvert_WallBody";
        var rebarInfos = obj["RebarData"][contructorOfRebar]["RebarConfigs"] as JArray;
        if (rebarInfos == null)
        {
            return (null, null);
        }
        var levelName = rebarInfos.First(p => p["Number"].Value<string>() == this.RebarGroupNumber)["LayerName"];
        return (levelName.ToString(), this.Grades);
    }
    protected string GetConstuctorInfoOfRebar(CulvertComponentType componentType, CulvertType culvertType)
    {
        if (componentType == CulvertComponentType.OrthogonalityCover && culvertType == CulvertType.SlabCulvert)
        {
            return "SlabCulvert_PositiveSlab";
        }
        if (componentType == CulvertComponentType.HeterotropicCover && culvertType == CulvertType.SlabCulvert)
        {
            return "SlabCulvert_CrookedSlab";
        }
        if (componentType == CulvertComponentType.CulvertBody && culvertType == CulvertType.SlabCulvert)
        {
            return "SlabCulvert_WallBody";
        }

        if (componentType == CulvertComponentType.Fondation && culvertType == CulvertType.SlabCulvert)
        {
            return "SlabCulvert_Basis";
        }
        if (componentType == CulvertComponentType.BraceSummer && culvertType == CulvertType.SlabCulvert)
        {
            return "SlabCulvert_BraceSummer";
        }
        if (componentType == CulvertComponentType.CulvertBody && culvertType == CulvertType.BoxCulvert)
        {
            return "BoxCulvert_Body";
        }
        if (componentType == CulvertComponentType.WingWall && culvertType == CulvertType.BoxCulvert)
        {
            return "BoxCulvert_WingWall";
        }
        if (componentType == CulvertComponentType.Tube && culvertType == CulvertType.CircularCulvert)
        {
            return "CircularCulvert_TubeCoupling";
        }
        return null;
    }
    public void CreateElementECProperty(Element element, List<Tuple<string, CustomProperty.TypeKind, bool, bool>> ecPropertyList)
    {
        this.AddCoverHiddenEcItemType();
        ItemTypeHelpers.AddItemType("钢筋属性", "钢筋信息", ecPropertyList);
        var itemTypeLibrary = ItemTypeHelpers.GetTypeLibraryFromName("钢筋属性");
        var itemtype = ItemTypeHelpers.GetItemTypeFromName(itemTypeLibrary, "钢筋信息");
        var dgnECInstance = ItemTypeHelpers.AttachItemType(itemtype, element);
        var ecDataList = ItemTypeHelpers.GetCSVData(this.EntityEcPropertyInfoFile);
        this.SetECInstanceValue(dgnECInstance, ecDataList);
        this.SaveStandardECProperty(dgnECInstance);
    }

    public void SetECInstanceValue(IDgnECInstance dgnECInstance, List<(string propertyName, string calculationBasis, string computationalFormula)> propertyData)
    {
        if (!propertyData.Any() || null == propertyData || null == dgnECInstance)
        {
            return;
        }
        var rebarData = this.CreateStandardECProperty();
        var eCProperties = dgnECInstance.ClassDefinition.Properties(true);
        foreach (var ecProperty in eCProperties.Where(p => p.DisplayLabel != "RebarHiddenData"))
        {
            var eCPropertyValue = dgnECInstance.FindPropertyValue(ecProperty.Name, false, false, false, false);
            var propertyItem = propertyData.FirstOrDefault(p => p.propertyName == ecProperty.DisplayLabel);
            if (eCPropertyValue == null || eCPropertyValue.IsReadOnly || propertyItem == (null, null, null))
            {
                continue;
            }
            if (string.IsNullOrWhiteSpace(propertyItem.computationalFormula))
            {
                dgnECInstance.SetValue<string>(ecProperty.Name, propertyItem.computationalFormula);
            }
            else if (propertyItem.computationalFormula.StartsWith("="))
            {
                var computationalFormula = GeneralHelpers.ConvertFormula(propertyItem.computationalFormula.Substring(1), rebarData);
                if (GeneralHelpers.IsContainPureString(computationalFormula, rebarData))
                {
                    dgnECInstance.SetValue<string>(ecProperty.Name, computationalFormula);
                }
                else
                {
                    var result = new DataTable().Compute(computationalFormula, "");
                    dgnECInstance.SetValue<string>(ecProperty.Name, result.ToString());
                }
            }
        }
        dgnECInstance.ScheduleChanges(dgnECInstance.Element);
        dgnECInstance.Element.ReplaceInModel(dgnECInstance.Element);
    }
    public abstract CurveVector CreateGuideLineOfRebar();

    /// <summary>
    /// 在原点位置绘制钢筋截面
    /// </summary>
    /// <returns></returns>
    public virtual CurveVector CreateRebarSection()
    {
        //绘制在0,0,0处绘制钢筋截面 rebarProfile
        DEllipse3d rebarProfile = DEllipse3d.FromCenterRadiusXY(new DPoint3d(0, 0, 0), this.Diameter * 0.5 * 0.001 * 10000);
        Bentley.DgnPlatformNET.Elements.EllipseElement rebarProfileElement = new(GeneralHelpers.ActiveDgnModel, null, rebarProfile);
        CurveVector secCur = CurvePathQuery.ElementToCurveVector(rebarProfileElement);
        return secCur;
    }
    public override string ToString()
    {
        var culvertType = _constructingEntity.ToString();
        return _constructingEntity.ToString() + "_" + this.RebarGroupNumber + "号钢筋";
    }


    public abstract List<(string standardName, string standValue)> CreateStandardECProperty();

    public void SaveStandardECProperty(IDgnECInstance dgnECInstance)
    {
        var retJObject = new JObject();
        foreach (var item in this.CreateStandardECProperty())
        {
            retJObject[item.standardName] = item.standValue;
        }

        // 属性赋值
        IEnumerable<IECProperty> eCProperties = dgnECInstance.ClassDefinition.Properties(true);
        foreach (IECProperty eCProperty in eCProperties)
        {
            if (eCProperty.DisplayLabel.Equals("RebarHiddenData"))
            {
                IECPropertyValue eCPropertyValue =
                    dgnECInstance.FindPropertyValue(eCProperty.Name, false, false, false, false);
                if (eCPropertyValue != null)
                {
                    var saveStr = retJObject.ToString(Newtonsoft.Json.Formatting.None);
                    dgnECInstance.SetValue<string>(eCProperty.Name, saveStr);
                }
            }
        }
        dgnECInstance.ScheduleChanges(dgnECInstance.Element);
        dgnECInstance.Element.ReplaceInModel(dgnECInstance.Element);
    }
    protected void AddCoverHiddenEcItemType()
    {
        List<Tuple<string, CustomProperty.TypeKind, bool, bool>> propertyTypeNames = new()
        {
            new Tuple<string, CustomProperty.TypeKind, bool, bool>("RebarHiddenData", CustomProperty.TypeKind.String, false, false)
        };
        ItemTypeHelpers.AddItemType("钢筋属性", "钢筋信息", propertyTypeNames);
    }
}